package com.fruit.logistics;

import com.fruit.pojo.logistics.*;
import com.fruit.service.logistics.LogisticsService;
import com.fruit.service.logistics.NoSuitableProxyException;
import com.fruit.service.logistics.RouteListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
 * 快递服务
 *
 * @author joe
 * @version 2018.02.05 14:43
 */
@Service("logisticsService")
@Slf4j
public class LogisticsServiceImpl implements LogisticsService {
    private static final List<RouteListener> LISTENERS = new ArrayList<>();
    /**
     * 各大快递代理集合
     */
    @Autowired
    private List<LogisticsProxyService> proxyServices;

    /**
     * 初始化方法
     * <p>
     * 如果需要增加一个快递只需要实现LogisticsProxyService接口然后在该方法加入实现实例即可，当前只有顺丰
     */
    @PostConstruct
    public void init() {
        log.info("初始化快递服务");
        log.info("找到的快递代理集合为：[{}]", proxyServices);
        proxyServices.forEach(service -> service.init(this));
        log.info("快递代理注册完毕");
    }

    @Override
    public void register(RouteListener listener) {
        if (listener == null) {
            throw new IllegalArgumentException("监听器不能为null");
        }
        LISTENERS.add(listener);
    }

    @Override
    public SysRoute routeNotify(String data, LogisticsType type) throws NoSuitableProxyException {
        log.info("收到{}路由通知：{}", type, data);
        LogisticsProxyService proxyService = searchProxy(type);
        SysRoute route = proxyService.routeNotify(data, type);
        log.info("[{}]的路由通知为：{}", type, route);
        if (route != null) {
            log.info("发布路由事件");
            LISTENERS.forEach(routeListener -> {
                try {
                    routeListener.exec(route);
                } catch (Throwable e) {
                    log.warn("监听器[{}]处理路由信息[{}]时发生了异常", routeListener, route, e);
                }
            });
        }
        return route;
    }

    @Override
    public SysLogisticsOrderResponse send(SysLogistics logistics) throws NoSuitableProxyException {
        //该方法需要实现，自动选择快递商家
        log.warn("该方法未实现，当前默认使用顺丰");
        return proxyServices.get(0).send(logistics);
    }

    @Override
    public SysLogisticsOrderResponse searchSend(LogisticsType type, String orderId) throws NoSuitableProxyException {
        log.info("查询[{}]的快递订单发送结果，参数为：{}", type, orderId);
        LogisticsProxyService proxyService = searchProxy(type);
        SysLogisticsOrderResponse response = proxyService.searchSend(type, orderId);
        log.info("[{}]的快递订单发送结果为：{}", type, response);
        return response;
    }

    @Override
    public SysRouteResponse searchRoute(LogisticsType type, String id, boolean isSys) throws NoSuitableProxyException {
        log.info("查询[{}]的路由信息，参数为：{}:{}", type, id, isSys);
        LogisticsProxyService proxyService = searchProxy(type);
        SysRouteResponse response = proxyService.searchRoute(type, id, isSys);
        log.info("查询[{}]的路由结果为：{}", type, response);
        return response;
    }

    @Override
    public SysLogisticsOrderResponse send(LogisticsType type, SysLogistics logistics) throws NoSuitableProxyException {
        log.info("创建[{}]的快递订单，参数为：{}", type, logistics);
        LogisticsProxyService proxyService = searchProxy(type);
        SysLogisticsOrderResponse response = proxyService.send(type, logistics);
        log.info("[{}]的快递订单请求结果为：{}", type, response);
        return response;
    }

    @Override
    public SysDeliverResponse searchDeliver(LogisticsType type, SysDeliver deliver) throws NoSuitableProxyException {
        log.debug("查询[{}]的时效，查询参数为：{}", type, deliver);
        LogisticsProxyService proxyService = searchProxy(type);
        SysDeliverResponse response = proxyService.searchDeliver(type, deliver);
        log.info("[{}]的时效查询结果为：{}", type, response);
        return response;
    }

    @Override
    public SysNewDeliverResponse searchDeliver(LogisticsType type, SysNewDeliver deliver) throws
            NoSuitableProxyException {
        log.debug("查询[{}]的时效（new），查询参数为：{}", type, deliver);
        LogisticsProxyService proxyService = searchProxy(type);
        SysNewDeliverResponse response = proxyService.searchDeliver(type, deliver);
        log.info("[{}]的时效查询结果为：{}", type, response);
        return response;
    }

    /**
     * 根据类型查找合适的快递代理
     *
     * @param type 代理
     * @return type对应的快递代理
     * @throws NoSuitableProxyException 当没有合适的快递代理时抛出该异常
     */
    private LogisticsProxyService searchProxy(LogisticsType type) throws NoSuitableProxyException {
        for (LogisticsProxyService proxyService : proxyServices) {
            if (proxyService.filter(type)) {
                return proxyService;
            }
        }
        throw new NoSuitableProxyException();
    }
}
